package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.DepartmentAddDTO;
import com.sky.dto.common.PageRequest;
import com.sky.dto.common.ParamsID;
import com.sky.dto.common.ParamsStatus;
import com.sky.dto.common.QueryParams;
import com.sky.entity.Department;
import com.sky.entity.Dict;
import com.sky.entity.Instructor;
import com.sky.exception.CommonException;
import com.sky.mapper.DepartmentMapper;
import com.sky.mapper.InstructorMapeer;
import com.sky.result.PageResult;
import com.sky.service.DepartmentService;
import com.sky.utils.TreeUtils;
import com.sky.vo.DepartmentListVO;
import com.sky.vo.DictVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DepartmentServiceImpl implements DepartmentService {
    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private InstructorMapeer instructorMapeer;
    /**
     * 获取所有的部门列表
     * @param queryParams  通用查询参数
     * @return
     */
    @Override
    public PageResult getAllDepartments(PageRequest<QueryParams> queryParams) {
        log.info("获取字典分类列表，queryParams: {}", queryParams);
        PageHelper.startPage(queryParams.getPageNum(), queryParams.getPageSize());
        List<Department> departments = departmentMapper.getDicDataAll(queryParams.getParams());
        PageInfo<Department> pageInfo = new PageInfo<>(departments);
        List<DepartmentListVO> results = pageInfo.getList().stream().map(department -> {
            DepartmentListVO vo = new DepartmentListVO();
            BeanUtils.copyProperties(department, vo);
            vo.setChildren(getChildrenRecursive(department.getId()));
            return vo;
        }).collect(Collectors.toList());
        return new PageResult(pageInfo.getTotal(), results);
//        Long total = page.getTotal();
//        List<Department> result = page.getResult();
//        List<DepartmentListVO> tree = result.stream()
//                .map(department -> {
//                    DepartmentListVO vo = new DepartmentListVO();
//                    BeanUtils.copyProperties(department, vo);
//                    vo.setChildren(getChildrenRecursive(department.getId()));
//                    return vo;
//                }).collect(Collectors.toList());
//        return new PageResult(total, tree);
    }
    /**
     * 新增部门
     * @param departmentAddDTO 部门添加DTO
     */
    @Override
    public void addDepartment(DepartmentAddDTO departmentAddDTO) {
        Department department = new Department();
        // 拷贝数据
        BeanUtils.copyProperties(departmentAddDTO, department);
        departmentMapper.addDepartment(department);
    }

    /**
     *  删除部门
     * @param ids 部门id
     */
    @Override
    public void deleteDepartment(ParamsID ids) {
        //TODO 后续补充部门不能删除的逻辑-部门下挂有竞赛信息的 不能删除！
        // 获取当前线程的用户id
        String currentId = BaseContext.getCurrentId();
        Instructor info = instructorMapeer.getInfoById(currentId);
        if(info.getPermissionLevel() != 0){
            throw new CommonException(MessageConstant.POWER_ERR);
        }else{
            ids.getIds().forEach(id -> {
                if(departmentMapper.getTopLevelDepartmentCount(id) > 0) {
                    throw new CommonException(MessageConstant.DELETE_ERR);
                }
                departmentMapper.deleteDepartmentByIds(id);
            });
        }
    }

    /**
     * 跟新部门信息
     * @param department
     */
    @Override
    public void updateDepartment(Department department) {
        departmentMapper.updateDepartment(department);
    }

    /**
     * 根据部门id查询此部门下所有的
     * @param id 部门id
     *  * @param deep 深度查询 0 否， 1 是
     * @return
     */
    @Override
    public List<Department> getDepartmentsById(String id, Integer deep) {
        if (deep == null || deep == 0) {
            // 只返回自己
            Department department = departmentMapper.getDepartmentById(id);
            return department != null ? Collections.singletonList(department) : Collections.emptyList();
        }
        // 深度查询：自己 + 所有子孙
        Set<String> visited = new HashSet<>();
        List<Department> result = new ArrayList<>();
        Department self = departmentMapper.getDepartmentById(id);
        if (self != null) {
            result.add(self);
        }
        List<Department> subs = getAllSubDepartments(id, visited);
        result.addAll(subs);
        return result;
    }


    /**
     * 传递部门id，获取此部门下所有的子部门id
     * @param id
     * @param deep 是否深度查询 0 否， 1 是
     * @return 返回的部门ids 组成的数组
     */
    @Override
    public List<String> getDepartmentIdsById(String id, Integer deep) {
        if (deep == null || deep == 0) {
            return Collections.singletonList(id);
        }
        Set<String> visited = new HashSet<>();
        Set<String> idSet = new LinkedHashSet<>();
        Department self = departmentMapper.getDepartmentById(id);
        if (self != null) {
            idSet.add(self.getId());
        }
        collectSubDepartmentIds(id, visited, idSet);
        return new ArrayList<>(idSet);
    }


    /**
     * 将部门链转为字符串路径（根部门-子部门-...-当前部门）
     */
    @Override
    public  String buildDepartmentPath(String id) {
        List<Department> departmentList = getDepartmentWithParents(id);
        if (departmentList == null || departmentList.isEmpty()) {
            return "";
        }
        // 反转顺序：当前部门 -> 根部门，变成根 -> 当前
        List<String> path = departmentList.stream()
                .map(Department::getName)
                .collect(Collectors.toList());
        Collections.reverse(path);
        return String.join("-", path);
    }

    /**
     * 获取所有部门列表 -- 部门树专用
     * @param queryParams
     * @return 返回list集合
     */
    @Override
    public List<Department> getAllDepartmentsList(QueryParams queryParams) {
        log.info("获取所有部门列表，queryParams: {}", queryParams);
        // 如果当前参数有部门id 则需要构造当前部门及其所有子部门的id数组
        resolveDepartmentFilter(queryParams);
        List<Department> result = departmentMapper.getDicDataAllList(queryParams);
        return result;
    }
    /**
     * 修改部门状态- 包括下属的部门启用的一个状态
     * @param paramsStatus
     */
    @Override
    public void updateDepartmentStatus(ParamsStatus paramsStatus) {
        List<String> ids = this.getDepartmentIdsById(paramsStatus.getId(), 1);
        departmentMapper.updateDepartmentStatus(ids, paramsStatus.getStatus());
    }
    //==========================BEGIN 工具方法==========================
    /**
     * 根据部门ID查询当前部门及其所有上级部门
     * @param id 部门id
     * @return 部门链（从当前部门开始，一直到根）xx-xx-xx
     */
    public List<Department> getDepartmentWithParents(String id) {
        List<Department> result = new ArrayList<>();
        Set<String> visited = new HashSet<>(); // 防止死循环
        findParentChain(id, result, visited);
        return result;
    }
    /**
     * 向上递归查找父部门
     */
    private void findParentChain(String id, List<Department> result, Set<String> visited) {
        if (id == null || visited.contains(id)) {
            return;
        }
        visited.add(id);
        Department dept = departmentMapper.getDepartmentById(id); // 查当前部门
        if (dept != null) {
            result.add(dept);
            findParentChain(dept.getPid(), result, visited); // 递归查父部门
        }
    }

    /**
     * 递归获取所有子部门
     * @param id 部门id
     * @param visited 已访问的部门id集合
     * @return
     */
    private List<Department> getAllSubDepartments(String id, Set<String> visited) {
        List<Department> result = new ArrayList<>();
        if (visited.contains(id)) {
            return result;
        }
        visited.add(id);
        List<Department> children = departmentMapper.getDepartmentsByPid(id);
        if (children != null && !children.isEmpty()) {
            result.addAll(children);
            for (Department dept : children) {
                List<Department> sub = getAllSubDepartments(dept.getId(), visited);
                result.addAll(sub);
            }
        }
        return result;
    }

    /**
     * 处理通用查询参数的（主要是部门数据转数组之类的！）
     * @param queryParams
     */
    @Override
    public  void resolveDepartmentFilter(QueryParams queryParams) {

        String departmentId = queryParams.getDepartmentId();
        if (departmentId != null && !departmentId.isEmpty()) {
            List<String> departmentIds = getDepartmentIdsById(queryParams.getDepartmentId(),1);
            log.info("========================================================================================");
            log.info("递归查询部门ID列表: {}", departmentIds);
            queryParams.setDepartmentId(null); // 清除原始字段，防止混用
            queryParams.setDepartmentIds(departmentIds); // 设置递归后的ID列表
        }
    }
    @Override
    public List<Department> getDepartmentPrent() {
        return departmentMapper.getDepartmentPrent();
    }


    /**
     * 递归收集子部门ID
     * @param id 部门ID
     * @param visited 已访问的部门ID集合
     * @param idSet 收集的部门ID集合
     */
    private void collectSubDepartmentIds(String id, Set<String> visited, Set<String> idSet) {
        if (visited.contains(id)) return;
        visited.add(id);
        List<Department> children = departmentMapper.getDepartmentsByPid(id);
        if (children != null && !children.isEmpty()) {
            for (Department dept : children) {
                idSet.add(dept.getId());
                collectSubDepartmentIds(dept.getId(), visited, idSet);
            }
        }
    }


    //==========================END 工具方法==========================
    private List<DepartmentListVO> getChildrenRecursive(String parentId) {
        List<Department> children = departmentMapper.getDepartmentsByPid(parentId);
        if (children.isEmpty()) {
            return new ArrayList<>();
        }
        return children.stream().map(child -> {
            DepartmentListVO vo = new DepartmentListVO();
            BeanUtils.copyProperties(child, vo);
            vo.setChildren(getChildrenRecursive(child.getId()));
            return vo;
        }).collect(Collectors.toList());
    }
}
